package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.service.TestService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author atguigu-mqx
 * @ClassName TestServiceImpl
 * @description: TODO
 * @date 2024年04月20日
 * @version: 1.0
 */
@Service
public class TestServiceImpl implements TestService {
    /*
        1.  在缓存中初始化一个key=num value=0;
        2.  获取缓存中的num
                true: 获取num数据并+1 放回缓存
                false: return;
     */
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public void testLock() {
        //  获取锁
        RLock lock = redissonClient.getLock("lock");
        //  上锁
        lock.lock();
        //  lock.lock(10,TimeUnit.SECONDS);
        //  尝试获取锁. 最大等待时间100s， 过期时间10s, 时间单位
        boolean res = false;
        try {
            res = lock.tryLock(100, 1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //  表示获取到锁.
        if (res) {
            try {
                //  执行业务逻辑
                //  获取缓存key的数据
                String num = this.redisTemplate.opsForValue().get("num");
                //  判断当前数据是否为空
                if (StringUtils.isEmpty(num)){
                    return;
                }
                int numValue = Integer.parseInt(num);
                //  将数据+1 放入缓存.
                this.redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
                //  解锁
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            } finally {
                //  解锁
                lock.unlock();
            }
        } else {
            System.out.println("未获取到锁.");
            // testLock();
        }

    }

    //    @Override
//    public void testLock() {
//        //  执行setnx key value;
//        //  执行 set lock ok ex 3 nx
//        String token = UUID.randomUUID().toString();
//        Boolean result = this.redisTemplate.opsForValue().setIfAbsent("lock",token,3, TimeUnit.SECONDS);
//        //  判断result
//        if (result){
//            //  执行成功获取到锁.
//            //  获取缓存key的数据
//            String num = this.redisTemplate.opsForValue().get("num");
//            //  判断当前数据是否为空
//            if (StringUtils.isEmpty(num)){
//                return;
//            }
//            int numValue = Integer.parseInt(num);
//            //  将数据+1 放入缓存.
//            this.redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
//            //  判断
//            String scriptText = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
//                    "then\n" +
//                    "    return redis.call(\"del\",KEYS[1])\n" +
//                    "else\n" +
//                    "    return 0\n" +
//                    "end";
//            //  执行lua 脚本删除。
//            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//            redisScript.setScriptText(scriptText);
//            redisScript.setResultType(Long.class);
//            this.redisTemplate.execute(redisScript, Arrays.asList("lock"),token);
////            if (token.equals(this.redisTemplate.opsForValue().get("lock"))){
////                //  执行完成之后，删除锁
////                this.redisTemplate.delete("lock");
////            }
//        } else {
//          //    没有获取到锁。
//            try {
//                Thread.sleep(100);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            testLock();
//        }
//    }
}
